package com.course.app.biz;

import com.course.app.api.data.*;
import com.course.app.transformer.*;
import com.course.domain.model.*;
import com.course.domain.service.*;
import com.course.util.DateUtils;
import com.course.util.TimeUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by Justin on 2017/5/17.
 */
@Component
public class AgendaBiz {

    private final AgendaService agendaService;
    private final CourseService courseService;
    private final ClassService classService;
    private final SpecService specService;
    private final TaskService taskService;
    private final UserService userService;

    @Autowired
    public AgendaBiz(AgendaService agendaService,
                     CourseService courseService,
                     ClassService classService,
                     SpecService specService,
                     TaskService taskService,
                     UserService userService) {
        this.agendaService = agendaService;
        this.courseService = courseService;
        this.classService = classService;
        this.specService = specService;
        this.taskService = taskService;
        this.userService = userService;
    }

    public AgendaInfo loadInfo(int studentId, int courseId) {
        return agendaService.loadInfo(studentId, courseId);
    }

    public AgendaDTO findAgendaByStudentId(int studentId, Date date) {
        Student student = userService.loadStudent(studentId);
        if (student == null) {
            return null;
        }
        int courseId = student.getCourseId();
        CourseInfo courseInfo = courseService.loadInfo(courseId);
        AgendaInfo agendaInfo = agendaService.loadInfo(studentId, courseId);
        if (courseInfo == null || agendaInfo == null) {
            return null;
        }
        int agendaId = agendaInfo.getId();
        LocalDate start = DateUtils.toLocalDate(courseInfo.getBeginDate());
        LocalDate begin = DateUtils.toLocalDate(agendaInfo.getBeginDate());
        LocalDate today = DateUtils.toLocalDate(date);
        if (today.isBefore(begin)) {
            today = begin;
        }
        int weekNow = date != null ? DateUtils.calcWeekIdx(start, today) : 1;
        int weekEnd = courseInfo.getWeeks() + 1;

        Map<Integer, TaskAudioDTO> audioDTOMap = TaskAudioTransformer.toAudioMap(taskService.findAudio(courseId));
        Map<Integer, TaskVideoDTO> videoDTOMap = TaskVideoTransformer.toVideoMap(taskService.findVideo(courseId));
        Map<Integer, TaskStoryDTO> storyDTOMap = TaskStoryTransfromer.toStoryMap(taskService.findStory(courseId));
        Map<Integer, TaskLearnDTO> learnDTOMap = TaskLearnTransformer.toLearnMap(taskService.findGroup(courseId));
        Map<Integer, TaskClassDTO> classDTOMap = TaskClassTransformer.toClassMap(taskService.findClass(courseId));
        Map<Integer, TaskEventDTO> eventDTOMap = TaskEventTransformer.toEventMap(taskService.findEvent(courseId));

        Map<Integer, Integer> classTimeMap = Maps.newHashMap();

        for (ClassPlan classPlan : classService.findPlanByStudentIdAndCourseId(studentId, courseId)) {
            classDTOMap.get(classPlan.getClassId()).setRoom(classPlan.getRoom());
            LocalTime localTime = DateUtils.toLocalTime(classPlan.getDate());
            int time = TimeUtils.toTime(localTime.getHour(), localTime.getMinute());
            classTimeMap.put(classPlan.getPlanId(), time);
        }

        CourseDTO courseDTO = CourseTransformer.toDTO(courseInfo, agendaInfo.getBeginDate());
        ResourceDTO resourceDTO = ResourceTransformer.toDTO(audioDTOMap, videoDTOMap, storyDTOMap);

        List<AgendaPlanDTO> planDTOS = Lists.newArrayListWithCapacity(weekEnd - weekNow);

        int parts = specService.findWeek(courseInfo.getSpecId()).size();
        List<AgendaWeek> agendaWeeks = findAgendaWeek(agendaId, parts);
        for (int weekIdx = weekNow; weekIdx < weekEnd; weekIdx++) {
            List<CourseWeek> courseWeeks = findCourseWeek(courseId, weekIdx, parts);
            planDTOS.addAll(AgendaTransformer.toList(start, weekIdx, courseWeeks, agendaWeeks, learnDTOMap, classDTOMap, eventDTOMap, classTimeMap));
        }

        return AgendaTransformer.toDTO(agendaId, courseDTO, resourceDTO, planDTOS);
    }

    private List<AgendaWeek> findAgendaWeek(int agendaId, int parts) {
        List<AgendaWeek> weeks = Lists.newArrayListWithCapacity(parts);
        for (int i = 0; i < parts; i++) {
            weeks.add(null);
        }
        for (AgendaWeek week : agendaService.findWeek(agendaId)) {
            weeks.set(week.getPartIdx() - 1, week);
        }
        return weeks;
    }

    private List<CourseWeek> findCourseWeek(int courseId, int weekIdx, int parts) {
        List<CourseWeek> weeks = Lists.newArrayListWithCapacity(parts);
        List<CoursePlan> plans = courseService.findPlan(courseId, weekIdx);
        for (int i = 0; i < parts; i++) {
            int partIdx = i + 1;
            CourseWeek week = new CourseWeek();
            week.setPartIdx(partIdx);
            weeks.add(week);
        }
        for (CoursePlan plan : plans) {
            int weekDay = plan.getWeekDay();
            int partIdx = plan.getPartIdx();
            weeks.get(partIdx - 1).setPlanByWeekDay(weekDay, plan);
        }
        return weeks;
    }
}

